#define _CRT_SECURE_NO_WARNINGS 1


//		《 Linux_24_文件系统 》

	《 文件的磁盘存储 》

1.物理磁盘：
计算机的文件都在磁盘存储：磁盘文件
如何存储?

2.了解磁盘的存储结构：
磁盘是一个外设，机械设备，特点：慢，性价比高
磁盘的表面由一些磁性物质组成，可以用这些磁性物质来记录二进制数据

磁盘读写的基本单位是扇区：512字节, 4KB
磁盘的盘面被划分成一个个磁道
这样的一个“圈”就是一个磁道(可以参考光碟,磁带)
1片 = n磁道(柱面)
1磁道 = m 扇区

一个磁道又被划分成一个个扇区，
每个扇区就是一个“磁盘块”
各个扇区存放的数据量相同(如512KB)

①.如何找到一个指定位置的扇区 ? 
任何一个扇区 CHS 定址法
a.找到指定的磁头       Header
b.找到指定的磁道(柱面) Cylinder
c.找到指定的扇区       Sector

文件其实就是在磁盘中占有几个扇区的问题!!

3.对磁盘的存储进行逻辑抽象：
我们走一遍OS对磁盘这样的设备进行管理和抽象
为什么?  OS直接用CHS，耦合度太高。
为了方便实现内核进行磁盘管理
	
分治思想：

【       一块磁盘         】
             ↓
【[C:盘] [ D ] [ E ] [ F ]】//一块磁盘分成不同区域进行管理：分区
             ↓
		[  D分区  ]
             ↓
【[分组][][][][][]  ...[][][][][][][][][][][][][]】
【[Boot Block][Block group 0]  ...[Block group N]】
 
 
【[1 个块][][][][][][][][]】   ...
【[8扇区=1块] [N个扇区...]】
 
       块组
[Block group 0]
     ↓超级块          组描述符表            块位图       节点位图      索引节点表          数据块
【[Super Block] [Group Descriptor Table] [Block Bitmap] [inode Bitmap] [inode Table] [ Data blocks(最大)]】


磁盘级文件系统
[Data blocks] 只存储文件内容
	 ↓
【[1 个块][][][][][][][][]】
【[][][][][][][][][][][][]】
【[][][][][][][][][][][][]】
【[][]    ... ...     [][]】
【[][][][][][][][][][][][]】
【[][][][][][][][][][][][]】
 
分批加载到内存：
可以按块加载到内存

【[许多线性地址...块] [][]】// 磁盘容量 / 4KB 就得到多少块
【[8扇区=1块] [N个扇区...]】//我们就得到一个数组 sector disk_array[N] 通过运算我们可以得到 index -> CHS 
抽象：文件 = 很多个 LBA 地址 



一般而言，OS未来和磁盘交互的时候
一次读取512 KB 1个扇区 有点小，所以一般一次读取 4KB
基本单位 : 4KB = 8*sector
1个块大小: 4KB =  8个连续的扇区
规定出来的!
文件 = 很多个块构成


		《 LBA 》
逻辑区块地址(Logical Block Address, LBA)
【1个块】 == 8个扇区【[][][][][][][][]】 
1*8 = 8 对于OS而言，我们读取数据，可以以块为单位了。
通过块号可以得出 ==> CHS
只要知道一个起始，和磁盘的总大小，有多少块，每个块的块号，如何转换到对应的多个CHS地址，!
CHS 就全都知道了!


		< CHS >

假设有1000个扇区，10个磁道
 1 磁道 = 100个扇区 
	
indek->CHS
index / 1000 = H
index % 1000 = temp; [0, 999]
temp / 100   = C
temp % 100   = S

假设 CHS = 500 个扇区
500 / 100 = 0  H = 0 
500 % 1000 = 500;
500 / 100 = 5; C = 5
500 % 100 = 0; S = 0



————————————————————————————————————————————

文件 = 内容 + 属性(属性也是数据)
        ↓
文件在磁盘存储，本质是:
文件的内容 + 文件的属性数据
        ↓
Linux 文件系统特定: 
文件内容 和 文件属性 分开存储

————————————————————————————————————————————

在每一个分区内部分组，然后写入文件系统的管理数据:
称之为：格式化!!!!
格式化:在磁盘中写入文件系统！


数据区:存放文件内容
Data blocks(数据块)

		< Block Bitmap >
块位图(Block Bitmap) :
Block Bitmap中记录着 Data Block中 哪个数据块已经被占用
哪个数据块没有被占用
比特位的位置，表示块号。比特位的内容，表示该块是否被占用

inode Table(i节点表)
i节点表 : 存放文件属性 如
文件大小，所有者，最近修改时间等... ...

Linux中文件的属性是一个大小固定的集合体。
struct inode //文件的属性 （inode大小一般：128 byte(字节)）
{
	int size;		//文件的大小
	mode_t mode;	//文件的权限
	int creater;	//文件的创建者
	int time;		//创建时间

	... ...
	int inode_number;//i节点号
	... ...
	int datablocks[N];//数据块
};

		< inode_number >
node内部，不包含文件名!内核层面，
每一个文件都要有inode number!
我们通过 inode号(inode_number) 标识个文件!

一个块一般有4KB
inode大小一般：128 byte(字节)
4KB = 4*1024 = 4096(字节)
4KB/128 = 4096/128 = 32
一个块 可以存 32个 inode(i节点表)
一个正常文件，一个inode属性集合。

		< inode Bitmap >
假如有：1000个文件 1000/32 = 312 
312个块就可以保存 1000个文件的属性
如何知道 inode 的使用情况呢？
inode位图(inode Bitmap)：
inode Bitmap：每个bit表示一个inode是否空闲可用。

		< 查看inode 号>
Linux 查看inode号：【1838290】
[a@a]$ ll - li
【1838290】 drwxrwxr - x 2 whb whb 4096 Apr 7 19:37 dir
【1838266】 -rw- rw- r-- 1 whb whb    0 Apr 7 19:37 file.txt

		< GDT >
Group Descriptor Table : 块组描述符，描述块组属性信息

		< Super Block >
超级块(Super Block) : 存放文件系统本身的结构信息。
记录的信息主要有 : 
bolck 和 inode的总量,
未使用的block和inode的数量，
一个 block 和 inode 的大小，
最近一次挂载的时间，
最近一次写入数据的时间，
最近一次检验磁盘的时间等 其他文件系统的相关信息。
Super Block的信息被破坏，可以说整个文件系统结构就被破坏了.

不是每个分组都有 Super Block 的！
但是有多个 Super Block，当磁盘出问题，或者
系统崩溃时提示：是否修复系统，就是
启用其它 Super Block 的数据。


————————————————————————————————————————————


我们寻找文件的时候，都必须先得到文件的 inode号
inode 编号是以分区为单位的！
不能跨分区访问，不同分区 inode号 可能重复。
在范围 [start_inode, end_inode] 中
通过 + - 起始位置， start_inode 就可以准确得出该区的 下标


int datablocks[N];//数据块
ext2 -> ext3 -> ext4
//一般大小为 15 
int datablocks[15]
{
	[0][1]...[10][11] 一一映射 
	[12] ==> [20] ==> [20,30,40...]一级映射
	[13] ==> 二级映射
	[14] ==> 三级映射...
}

如果内容过大，可以跨组访问，但是建议放在同一个分组里面
磁盘进行寻址的时候，在不连续的分组里访问，效率会很慢。

//————————————————————————————————————————————

命令：	《 stat 》 统计
		
[a@192 bb]$ stat file.txt	//统计:file.txt
File : ‘file.txt’
Size : 0         	Blocks : 0          IO Block : 4096   regular empty file
Device : 803h / 2051d	Inode : 28319694    Links : 1
Access : (0664 / -rw - rw - r--)  Uid : (1000 / a)   Gid : (1000 / a)
Context : unconfined_u : object_r : user_home_t : s0
Access : 2024 - 05 - 05 05 : 29 : 11.047382331 - 0700
Modify : 2024 - 05 - 05 05 : 29 : 11.047382331 - 0700
Change : 2024 - 05 - 05 05 : 29 : 11.047382331 - 0700
Birth : -
[a@192 bb]$

//显示当前目录的内容 以及 inode 号
[a@192 bb]$ ls - li
total 16
【28319694】 - rw - rw - r--. 1 a a    0 May  5 05 : 29 【file.txt】
[a@192 bb]$ cat file.txt  //当我们打开文件时，系统就是统过 文件名与 inode 的映射关系找到里面的内容。

//去掉目录 r 权限
[a@192 bb]$ chmod u - r dir 
可以打开文件，可以创建内容 ...，但是无法查看
[a@192 bb]$ cd dir
[a@192 dir]$ ls
ls : cannot open directory . : Permission denied


//————————————————————————————————————————————

//			《 目录 》

你凭什么直接拿到了inode编号
我们一直用的可是文件名啊 !!!

目录也是文件 
目录 = 文件属性 + 文件内容
                  文件内容:文件名和inode编号的映射关系!

1.一个目录下不能建立同名文件
2.查找文件的顺序 ， 文件名->inode编
号
3.
目录的 r 
本质是是否允许我们读取目录的内容
文件名 : inode的映射关系!!

目录的 w
新建文件，最后一定要向当前所处的目录内容中
写入，文件名和inode的映射关系.
4.如何理解一个文件的增删查改？

删：inode Bitmap 节点位图 由1置为 0


//————————————————————————————————————————————

找到指定的文件 -> 文件所在的目录 -> 打开 -> 根据文件名:inode->目标文件的inode

目录也是文件

目录也有自己的:inode
[a@192 bb]$ pwd
home/whb/111/code/lesson22/dir		// 逆向的路径解析 --- OS自己做的!
为什么我们在linux中，定位一个文件，在任何时候，都要有路径的原因!!!

Linux 会缓存路径结构



————————————————————————————————————————————


		《 dd 》

从一个文件读入，把数据写入到另一个文件里，可以形成一个大文件

         从文件读,  写到当前目录disk.img, 块大小1M, 一共10个块
[a@192 dir]$ dd if=/dev/zero of=disk.img  bs=1M  count=10
10 + 0 records in			
10 + 0 records out
10485760 bytes(10 MB) copied, 0.00524775 s, 2.0 GB / s
[a@192 dir]$


查看 disk.img文件大小： = 10M
[a@192 dir]$ du - h disk.img
10M	disk.img 
[a@192 dir]$


分区 -> 写入文件系统(格式化) -> 挂载到指定的目录下 -> 进入该目录 -> 在指定的分区中进行文件操作

[a@192 dir]$ mount disk.img mymnt

[a@192 dir]$ df - h
Filesystem      Size  Used Avail Use % Mounted on
devtmpfs        471M     0  471M   0 % / dev
tmpfs           487M     0  487M   0 % / dev / shm
	... ...
tmpfs            98M   28K   98M   1 % / run / user / 1000
dev/loop0       8.7M  172K  7.9M   3% /home/whb/111/code/lesson22/dir/mymnt

卸载分区：
[a@192 dir]$ sudo umount mymnt
删除文件：mymnt
[a@192 dir]$ rm mymnt / -rf

 
一个文件其实在访问之前，都是先有目录的!!!
 A / b / c / d / ...

目录通常是谁提供的呢 ? ? ? 
你或者你的进程早就已经提供了!!!! cwd->  [pwd查看路径]
内核文件系统提前写入并组织好，然后我们提供的!!!

————————————————————————————————————————————

Linux内核在被使用的时候，一定存在大量的解析完毕的路径，
要不要对访问到的路径做管理呢 ? ? ? ?
先描述，在组织!!!

//路径缓存
struct dentry
{
	//类似
	struct dentry* next
	
	//实际 (listnode list;)
	//路径解析的信息，一个文件一个dentry
	struct file*	//--> 找到对应的文件
};
	
————————————————————————————————————————————
